import { Injectable, Logger } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { MountLevelExperienceEntity } from "../entities/mount-level-experience.entity";

@Injectable()
export class MountLevelExperienceService {
  private readonly logger = new Logger(MountLevelExperienceService.name);

  constructor(
    @InjectRepository(MountLevelExperienceEntity)
    private readonly mountLevelExperienceRepository: Repository<MountLevelExperienceEntity>
  ) {}

  /**
   * 根据等级获取坐骑经验数据
   * @param level 等级
   * @returns 坐骑等级经验数据
   */
  async getMountLevelData(
    level: number
  ): Promise<MountLevelExperienceEntity | null> {
    try {
      return await this.mountLevelExperienceRepository.findOne({
        where: { level },
      });
    } catch (error) {
      this.logger.error(`获取坐骑等级数据失败: level=${level}`, error);
      throw error;
    }
  }

  /**
   * 根据经验值获取当前等级
   * @param experience 当前经验值
   * @returns 当前等级
   */
  async getLevelByExperience(experience: number): Promise<number> {
    try {
      // 查找最大的等级，其经验值小于等于当前经验值
      const result = await this.mountLevelExperienceRepository
        .createQueryBuilder("mount_level")
        .where("mount_level.experience <= :experience", { experience })
        .orderBy("mount_level.level", "DESC")
        .limit(1)
        .getOne();

      return result ? result.level : 1;
    } catch (error) {
      this.logger.error(
        `根据经验值获取等级失败: experience=${experience}`,
        error
      );
      throw error;
    }
  }

  /**
   * 获取升级到下一级需要的经验值
   * @param currentLevel 当前等级
   * @returns 升级到下一级需要的经验值
   */
  async getExpToNextLevel(currentLevel: number): Promise<number | null> {
    try {
      // 改为使用 experience 字段（总经验差）
      const currentLevelData = await this.getMountLevelData(currentLevel);
      const nextLevelData = await this.getMountLevelData(currentLevel + 1);
      if (!currentLevelData || !nextLevelData) {
        return null;
      }
      const diff =
        Number(nextLevelData.experience) - Number(currentLevelData.experience);
      return diff > 0 ? diff : 0;
    } catch (error) {
      this.logger.error(
        `获取升级经验失败: currentLevel=${currentLevel}`,
        error
      );
      throw error;
    }
  }

  /**
   * 获取当前等级训练一次获得的经验值
   * @param level 等级
   * @returns 训练一次获得的经验值
   */
  async getExpPerTraining(level: number): Promise<number> {
    try {
      const levelData = await this.getMountLevelData(level);
      if (!levelData) {
        // 如果找不到数据，返回默认值
        return 7500;
      }
      return levelData.expPerTraining;
    } catch (error) {
      this.logger.error(`获取训练经验失败: level=${level}`, error);
      throw error;
    }
  }

  /**
   * 获取升级到下一级需要的训练次数
   * @param currentLevel 当前等级
   * @returns 升级到下一级需要的训练次数
   */
  async getTrainingCountToNextLevel(currentLevel: number): Promise<number> {
    try {
      const levelData = await this.getMountLevelData(currentLevel);
      if (!levelData) {
        return 1;
      }
      return levelData.trainingCount;
    } catch (error) {
      this.logger.error(
        `获取训练次数失败: currentLevel=${currentLevel}`,
        error
      );
      throw error;
    }
  }

  /**
   * 获取坐骑经验进度信息
   * @param currentExperience 当前经验值
   * @returns 经验进度信息
   */
  async getMountExperienceProgress(currentExperience: number): Promise<{
    currentLevel: number;
    currentLevelExp: number;
    nextLevelExp: number | null;
    expToNext: number | null;
    progress: number; // 0-100的进度百分比
    expPerTraining: number;
    trainingCountToNext: number;
  }> {
    try {
      const currentLevel = await this.getLevelByExperience(currentExperience);
      const currentLevelData = await this.getMountLevelData(currentLevel);

      if (!currentLevelData) {
        throw new Error(`未找到等级 ${currentLevel} 的数据`);
      }

      const nextLevelData = await this.getMountLevelData(currentLevel + 1);

      if (!nextLevelData) {
        // 已经是最高等级
        return {
          currentLevel,
          currentLevelExp: currentExperience,
          nextLevelExp: null,
          expToNext: null,
          progress: 100,
          expPerTraining: currentLevelData.expPerTraining,
          trainingCountToNext: 0,
        };
      }

      const expToNext = nextLevelData.experience - currentLevelData.experience;
      const currentLevelProgress =
        currentExperience - currentLevelData.experience;
      const progress = Math.min(100, (currentLevelProgress / expToNext) * 100);

      return {
        currentLevel,
        currentLevelExp: currentExperience,
        nextLevelExp: nextLevelData.experience,
        expToNext,
        progress: Math.round(progress * 100) / 100, // 保留两位小数
        expPerTraining: currentLevelData.expPerTraining,
        trainingCountToNext: currentLevelData.trainingCount,
      };
    } catch (error) {
      this.logger.error(
        `获取坐骑经验进度失败: currentExperience=${currentExperience}`,
        error
      );
      throw error;
    }
  }

  /**
   * 获取所有坐骑等级数据
   * @returns 所有坐骑等级经验数据
   */
  async getAllMountLevels(): Promise<MountLevelExperienceEntity[]> {
    try {
      return await this.mountLevelExperienceRepository.find({
        order: { level: "ASC" },
      });
    } catch (error) {
      this.logger.error("获取所有坐骑等级数据失败", error);
      throw error;
    }
  }

  /**
   * 获取坐骑等级范围数据
   * @param startLevel 起始等级
   * @param endLevel 结束等级
   * @returns 坐骑等级范围数据
   */
  async getMountLevelsInRange(
    startLevel: number,
    endLevel: number
  ): Promise<MountLevelExperienceEntity[]> {
    try {
      return await this.mountLevelExperienceRepository
        .createQueryBuilder("mount_level")
        .where("mount_level.level >= :startLevel", { startLevel })
        .andWhere("mount_level.level <= :endLevel", { endLevel })
        .orderBy("mount_level.level", "ASC")
        .getMany();
    } catch (error) {
      this.logger.error(
        `获取坐骑等级范围数据失败: startLevel=${startLevel}, endLevel=${endLevel}`,
        error
      );
      throw error;
    }
  }

  /**
   * 获取最高等级
   * @returns 最高等级
   */
  async getMaxLevel(): Promise<number> {
    try {
      const result = await this.mountLevelExperienceRepository
        .createQueryBuilder("mount_level")
        .select("MAX(mount_level.level)", "maxLevel")
        .getRawOne();

      return result?.maxLevel || 1;
    } catch (error) {
      this.logger.error("获取最高等级失败", error);
      throw error;
    }
  }

  /**
   * 检查等级是否存在
   * @param level 等级
   * @returns 等级是否存在
   */
  async levelExists(level: number): Promise<boolean> {
    try {
      const count = await this.mountLevelExperienceRepository.count({
        where: { level },
      });
      return count > 0;
    } catch (error) {
      this.logger.error(`检查等级是否存在失败: level=${level}`, error);
      throw error;
    }
  }
}
